package br.unicamp.ic.sgct.server.dominio.servicos;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;

import br.unicamp.ic.sgct.client.aplicacao.conferencia.ConferenciaService;
import br.unicamp.ic.sgct.client.dominio.exception.InfraException;
import br.unicamp.ic.sgct.client.dominio.to.AreaTO;

import br.unicamp.ic.sgct.client.dominio.to.AutorTO;
import br.unicamp.ic.sgct.client.dominio.to.ConferenciaTO;
import br.unicamp.ic.sgct.client.dominio.to.SessaoTO;
import br.unicamp.ic.sgct.client.dominio.to.TrabalhoTO;
import br.unicamp.ic.sgct.server.dominio.entidades.Area;

import br.unicamp.ic.sgct.server.dominio.entidades.Autor;
import br.unicamp.ic.sgct.server.dominio.entidades.Conferencia;
import br.unicamp.ic.sgct.server.dominio.entidades.Trabalho;

import br.unicamp.ic.sgct.server.recursos.persistencia.BasicCrudDAO;
import br.unicamp.ic.sgct.server.recursos.persistencia.LOGGER;

import br.unicamp.ic.sgct.server.recursos.persistencia.LoaderDB;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class ConferenciaServiceImpl extends RemoteServiceServlet implements
        ConferenciaService {

    private BasicCrudDAO<Conferencia, Long> dao = new BasicCrudDAO<Conferencia, Long>(Conferencia.class);

    @Override
    public ConferenciaTO obterConferencia(long id) throws InfraException, Exception {
        LOGGER.debug("\nConferenciaServiceImpl :: obterConferencia(id) acionado");
        try {
            Conferencia conferencia = dao.findById(id);
            return conferencia == null ? null : conferencia.getTo();
        } catch (Throwable e) {
            LOGGER.error("obterConferencia", new InfraException(e));
            throw new InfraException(e);
        }

    }

    @Override
    public List<AreaTO> obterListaAreasConferencia(long id) throws InfraException, Exception {
        try {
            LOGGER.debug("obterConferenciasDisponiveis");
            Conferencia conf = dao.findById(id);
            Set<Area> areas = conf.getAreas();
            List<AreaTO> tos = new ArrayList<AreaTO>();
            if (conf != null) {
                for (Area area : areas) {
                    tos.add(area.getTo());
                }
            }
            return tos;
        } catch (Exception e) {
            LOGGER.error("obterConferencia", e);
            throw new InfraException(e);
        }
    }

    @Override
    public List<ConferenciaTO> obterConferenciasDisponiveis() throws InfraException, Exception {
        try {
            LOGGER.debug("obterConferenciasDisponiveis");
            return listarConferencias(Conferencia.findByTerminoChamadaTrabalhosMaiorIgualCurrentDate);
        } catch (Exception e) {
            LOGGER.error("obterConferencia", e);
            throw new InfraException(e);
        }

    }

    @Override
    public List<ConferenciaTO> listarConferenciasAbertas() throws InfraException, Exception {
        try {
            LOGGER.debug("obterConferenciasDisponiveis");
            return listarConferencias(Conferencia.findByTerminoMaiorIgualCurrentDate);
        } catch (Exception e) {
            LOGGER.error("obterConferencia", e);
            throw new InfraException(e);
        }
    }

    /**
     *
     */
    private List<ConferenciaTO> listarConferencias(String query) throws InfraException, Exception {
        LOGGER.debug("\nConferenciaServiceImpl :: listarConferencias() acionado");

        List<Conferencia> lstConfBD = null;
        List<ConferenciaTO> lstConferencias = new ArrayList<ConferenciaTO>();

        try {
            lstConfBD = dao.consultaQueryList(query);
            if (lstConfBD != null && !lstConfBD.isEmpty()) {
                for (Conferencia conferencia : lstConfBD) {
                    ConferenciaTO to = new ConferenciaTO();
                    lstConferencias.add(conferencia.getTo());
                }
            }
        } catch (Exception e) {
            LOGGER.error("obterConferenciasDisponiveis", e);
            throw new InfraException("InfraException: " + e.getMessage());
        }
        return lstConferencias;
    }

  
    /**
     *
     * @param List<ConferenciaTO>
     */
    private void printlnDados(List<ConferenciaTO> lstConfTo) {
        System.out.println("=========[ DADOS CONFERENCIA ]=========");
        if (lstConfTo != null && lstConfTo.size() > 0) {
            for (ConferenciaTO conferenciaTO : lstConfTo) {
                printlnDados(conferenciaTO);
            }
        }
        System.out.println("=======================================");
    }

    public TrabalhoTO getTrabalhoTO(EntityManager em, Trabalho t) {
        TrabalhoTO to = t.getTo();
        em.clear();
        Trabalho t2 = em.merge(t);
        //
        to.setPreletor(t2.getPreletor().getPreletorTO());
        to.setAutores(new ArrayList<AutorTO>());
        em.clear();
        t2 = em.merge(t2);
        Set<Autor> autores = t2.getAutores();
        for (Autor autor : autores) {
            to.getAutores().add(autor.getAutorTO());
        }
        return to;
    }

    /**
     *
     * @param ConferenciaTO
     */
    private void printlnDados(ConferenciaTO confTo) {
        System.out.println("Conferencia = " + confTo.getTitulo());
        System.out.println("Centro conv. = " + confTo.getCentroConvencao().toString());

        System.out.println("Sessoes da conf.: \n\n");
        List<SessaoTO> lstSessoesTo = confTo.getSessoesConferencia();
        if (lstSessoesTo != null && lstSessoesTo.size() > 0) {
            for (SessaoTO sessaoTo : lstSessoesTo) {
                System.out.println(sessaoTo.toString());
            }
        } else {
            System.out.println("*** Lista Sessoes conferencia nao carregada para conferencia "
                    + confTo.getTitulo());
        }

    }

    @Override
    public void destroy() {
        try {

            LoaderDB.getInstance().stopHSQLDB();
            super.destroy();
        } catch (Exception ex) {
            Logger.getLogger(ConferenciaServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
